package com.snow.useviewdemo.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by zhaoyt on 3/15/23.
 * Describe: switch开关
 */
public class CheckSwitchView extends View {

    private Paint mBackPaint;
    private Paint mPointPaint;
    private static final float mStrokeWidth = 5;
    public static final int CHECK_COLOR = Color.parseColor("#1971FF");
    public static final int UNCHECK_COLOR = Color.parseColor("#C9CDD4");
    private long mStartTime;
    private long mTargetTime;
    private long mDuration = -1;
    private int mLeftStartX;
    private int mLeftTargetX;
    private int mRightStartX;
    private int mRightTargetX;
    private long mRightStartTime;
    private long mRightTargetTime;
    private long mRightDuration = -1;
    private boolean isPlayingRight = false;
    private boolean isPlaying = false;
    private boolean isChecked = false;
    private int mPointRadius;
    private int checkColor = CHECK_COLOR;
    private int unCheckColor = UNCHECK_COLOR;
    private int pointColor = Color.parseColor("#ffffffff");
    private OnCheckedChangeListener mOnCheckedlistener;

    public CheckSwitchView(Context context) {
        this(context, null, 0);
    }

    public CheckSwitchView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CheckSwitchView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mBackPaint = new Paint();
        mBackPaint.setAntiAlias(true);
        mBackPaint.setStyle(Paint.Style.FILL);
        mBackPaint.setStrokeWidth(mStrokeWidth);

        mPointPaint = new Paint();
        mPointPaint.setAntiAlias(true);
        mPointPaint.setStyle(Paint.Style.FILL);
        mPointPaint.setStrokeWidth(mStrokeWidth);

        setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isPlayingAnimation()) {
                    return;
                }
                setChecked(!isChecked);
                initAnimator();
            }
        });
    }

    private void initAnimator() {
        mStartTime = System.currentTimeMillis();
        mDuration = isChecked ? 100 : 100;
        mTargetTime = mStartTime + mDuration;

        mRightStartTime = System.currentTimeMillis();
        mRightDuration = isChecked ? 100 : 100;
        mRightTargetTime = mRightStartTime + mRightDuration;
        isPlaying = true;
        isPlayingRight = true;
        invalidate();
    }

    private boolean isPlayingAnimation() {
        return isPlaying || isPlayingRight;
    }

    public void setSwitchPointColor(int pointColor) {
        this.pointColor = pointColor;
    }

    public void setSwitchColor(int checkColor, int unCheckColor) {
        this.checkColor = checkColor;
        this.unCheckColor = unCheckColor;
        invalidate();
    }

    public void setChecked(boolean check) {
        if (mOnCheckedlistener != null && check != isChecked) {
            mOnCheckedlistener.onCheckedChanged(this, check);
        }
        isChecked = check;
    }

    public boolean isChecked() {
        return isChecked;
    }

    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        mOnCheckedlistener = listener;
    }


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            mPointRadius = (getHeight() - dip2px(getContext(), 8)) / 2;
            mLeftStartX = mPointRadius + dip2px(getContext(), 5);
            mLeftTargetX = getWidth() - mPointRadius - dip2px(getContext(), 5);
            mRightStartX = mLeftStartX;
            mRightTargetX = mLeftTargetX;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mBackPaint.setColor(getCurColor());
        drawBacRectCir(canvas, getHeight() / 2, mBackPaint);
        mPointPaint.setColor(pointColor);
        drawPointRectCir(canvas, mPointRadius, getLeftCenterX(), getRightCenterX(), getHeight() / 2, mPointPaint);
        if (isPlaying || isPlayingRight) {
            invalidate();
        }
    }

    private void drawBacRectCir(Canvas canvas, int radius, Paint paint) {
        canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), radius, radius, paint);
    }

    private void drawPointRectCir(Canvas canvas, int radius, int leftCenterX, int rightCenterX, int centerY, Paint paint) {
        canvas.drawRoundRect(new RectF(leftCenterX - radius, centerY - radius, rightCenterX + radius, centerY + radius), radius, radius, paint);
    }

    private int getCurColor() {
        return isChecked ? checkColor : unCheckColor;
    }


    private int getLeftCenterX() {
        int currentLeftCenerX = isChecked ? mLeftStartX : mLeftTargetX;
        if (isPlaying) {
            float ratio = ((float) (System.currentTimeMillis() - mStartTime) / mDuration) * (isChecked ? 1 : -1);
            currentLeftCenerX += (mLeftTargetX - mLeftStartX) * ratio;
            if ((isChecked && currentLeftCenerX >= mLeftTargetX) ||
                    !isChecked && currentLeftCenerX <= mLeftStartX) {
                isPlaying = false;
            }
        } else {
            return isChecked ? mLeftTargetX : mLeftStartX;
        }
        if (currentLeftCenerX > mLeftTargetX) {
            currentLeftCenerX = mLeftTargetX;
        }
        if (currentLeftCenerX < mLeftStartX) {
            currentLeftCenerX = mLeftStartX;
        }
        return currentLeftCenerX;
    }

    private int getRightCenterX() {
        int currentRightX = isChecked ? mRightStartX : mRightTargetX;
        if (isPlayingRight) {
            float ratio = ((float) (System.currentTimeMillis() - mRightStartTime) / mRightDuration) * (isChecked ? 1 : -1);
            currentRightX += (mRightTargetX - mRightStartX) * ratio;
            if ((isChecked && currentRightX >= mRightTargetX) ||
                    !isChecked && currentRightX <= mRightStartX) {
                isPlayingRight = false;
            }
        } else {
            return isChecked ? mRightTargetX : mRightStartX;
        }
        if (currentRightX > mRightTargetX) {
            currentRightX = mRightTargetX;
        }
        if (currentRightX < mRightStartX) {
            currentRightX = mRightStartX;
        }
        return currentRightX;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isPlayingAnimation()) {
            return true;
        }
        return super.onTouchEvent(event);
    }

    public interface OnCheckedChangeListener {
        void onCheckedChanged(View view, boolean isChecked);
    }

    private int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
}
